from django_filters.rest_framework import DjangoFilterBackend
from django.http import JsonResponse

from rest_framework import viewsets
from rest_framework.filters import SearchFilter
from rest_framework.filters import OrderingFilter
from rest_framework.response import Response

from XApiTestServer.pagination import MyPageNumberPagination
from XApiTestServer.serializers import AuthSerializer,AuthSumSerializer

from XApiTestServer.utils.test_auth import *
from XApiTestServer.utils.response import *
from XApiTestServer.utils.convertor import *
from XApiTestServer.utils.auth import get_username

import logging


logger = logging.getLogger('XApiTestServer')


def testauth(request):
    kwargs = json.loads(request.body.decode('utf-8'))
    auth_id = kwargs['id']
    config_id = kwargs.get('cfg_id', None)
    logger.info("Auth id:{auth_id}, Config id:{config_id}".format(auth_id=auth_id, config_id=config_id))

    try:
        token_map = get_token_map(auth_id, config_id)

        auth_key, auth_value = list(token_map.items())[0]
        logger.info("token key:{auth_key}, token value:{auth_value}".format(auth_key=auth_key, auth_value=auth_value))

        response_token_map = {
            'token_key':auth_key,
            'token_value': auth_value
        }
        response_body = SUCCESS_INFO
        response_body['data'] = response_token_map
        return JsonResponse(response_body)

    except Exception as e:
        response_body = TOKEN_FAILED
        response_body['msg'] = e
        return JsonResponse(response_body, encoder=ResponseExceptionEncoder, json_dumps_params={'ensure_ascii':False})


class AuthViewSet(viewsets.ModelViewSet):
    queryset = TestAuth.objects.all()
    serializer_class = AuthSerializer
    pagination_class = MyPageNumberPagination
    filter_backends = (OrderingFilter, SearchFilter, DjangoFilterBackend)
    search_fields = ('name',)
    filterset_fields = ('belong_project', )
    ordering_fields = ('update_time', )


    def nameValidator(self, project_id, authname, auth_id = None):
        if auth_id:
            actualname = TestAuth.objects.filter(id=auth_id).values('name')
            if actualname[0]['name'] == authname:
                return False
            else:
                authlist = TestAuth.objects.filter(belong_project=project_id).values('name')
                for a in authlist:
                    if a['name'] == authname:
                        return True
                    else:
                        continue
                return False
        else:
            authlist = TestAuth.objects.filter(belong_project=project_id).values('name')
            for a in authlist:
                if a['name'] == authname:
                    return True
                else:
                    continue
            return False

    def create(self, request, *args, **kwargs):
        if request.data['auth_type'] == 'Basic Authentication':
            if request.data['name'] == '' or request.data['auth_type'] == '' or request.data['belong_project'] == '' or request.data['user_name'] == '' or request.data['password'] == '' or request.data['auth_url'] == '':
                return Response(VERIFY_FIELDS_HINT, status=status.HTTP_201_CREATED)
            request.data['request'] = None
        else:
            if request.data['name'] == '' or request.data['auth_type'] == '' or request.data['belong_project'] == '' or request.data['request']['header_token_key'] == '' or request.data['request']['extract'] == '':
                return Response(VERIFY_FIELDS_HINT, status=status.HTTP_201_CREATED)
            if request.data['request']['request']['url']:
                request.data['auth_url'] = request.data['request']['request']['url']

            request.data['request'] = vue_request_to_db(request.data['request'])
            request.data['request'] = str(request.data['request'])

        token = request.META.get("HTTP_X_TOKEN", None)
        username=get_username(token)
        request.data['author'] = username

        if self.nameValidator(request.data['belong_project'], request.data['name']):
            return Response(AUTH_EXISTS, status=status.HTTP_201_CREATED)

        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            self.perform_create(serializer)
            headers = self.get_success_headers(serializer.data)
            response_body = SUCCESS_ADD
            response_body['data'] = serializer.data
            logger.info("create auth, the content is:{content}".format(content=response_body['data']))
            return Response(response_body, status=status.HTTP_200_OK, headers=headers)
        else:
            response_body = {'msg': '{msg}'.format(msg=serializer.errors)}
            return Response(response_body, status=status.HTTP_200_OK)

    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)

        response_body = SUCCESS_INFO
        response_body['data'] = serializer.data

        if instance.auth_type == 'Basic Authentication':
            response_body['data']['request'] = {
                'request': {'url': '', 'method': 'POST', 'type': 'data', 'content': [], 'headers': []}, 'extract': '',
                'header_token_key': ''}
            logger.info("get auth info:{body_value}".format(body_value=response_body['data']))
            return Response(response_body)
        else:
            response_body['data']['request'] = db_request_to_vue(response_body['data']['request'])

            response_body['data']['auth_url'] = ''
            request_key_list = list(response_body['data']['request']['request'].keys()).copy()
            if 'headers' not in request_key_list:
                response_body['data']['request']['request']['headers'] = []
            logger.info("get auth info:{body_value}".format(body_value=response_body['data']))
            return Response(response_body)

    def update(self, request, *args, **kwargs):
        if request.data['auth_type'] == 'Basic Authentication':
            if request.data['name'] == '' or request.data['auth_type'] == '' or request.data['belong_project'] == '' or request.data['user_name'] == '' or request.data['password'] == '' or request.data['auth_url'] == '':
                return Response(VERIFY_FIELDS_HINT, status=status.HTTP_201_CREATED)
            request.data['request'] = None
        else:
            if request.data['name'] == '' or request.data['auth_type'] == '' or request.data['belong_project'] == '' or request.data['request']['header_token_key'] == '' or request.data['request']['extract'] == '':
                return Response(VERIFY_FIELDS_HINT, status=status.HTTP_201_CREATED)

            if request.data['request']['request']['url']:
                request.data['auth_url'] = request.data['request']['request']['url']
            request.data['user_name'] = None
            request.data['password'] = None

            request.data['request'] = vue_request_to_db(request.data['request'])
            request.data['request'] = str(request.data['request'])

        token = request.META.get("HTTP_X_TOKEN", None)
        username=get_username(token)
        request.data['author'] = username

        if self.nameValidator(request.data['belong_project'], request.data['name'],request.data['id']):
            return Response(AUTH_EXISTS, status=status.HTTP_201_CREATED)

        serializer = self.get_serializer(data=request.data)
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        if serializer.is_valid(raise_exception=True):
            self.perform_update(serializer)

            response_body = SUCCESS_UPDATE
            response_body['data'] = serializer.data
            logger.info("The auth with id {id_value} is updated,the update content is:{content}".format(id_value=request.data['id'],content=response_body['data']))
            return Response(response_body)
        else:
            return Response(response_format(VERIFY_FIELDS_HINT, serializer.errors), status=status.HTTP_200_OK)

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        logger.info("delete the auth, id is:{id_value}".format(id_value=instance.id))
        self.perform_destroy(instance)
        response_body = SUCCESS_DEL
        return Response(response_body)


class AuthSumViewSet(viewsets.ModelViewSet):
    queryset = TestAuth.objects.all()
    serializer_class = AuthSumSerializer
    filter_backends = (OrderingFilter, SearchFilter, DjangoFilterBackend)
    filterset_fields = ('name',)
    ordering_fields = ('update_time',)

    def list(self, request, *args, **kwargs):
        queryset = TestAuth.objects.all()

        serializer = self.get_serializer(queryset, many=True)

        response_body = SUCCESS_LIST
        response_body['results'] = serializer.data

        return Response(response_body)
